﻿
Imports std
Imports storoomc

Public MustInherit Class storoomOper_hash
    Inherits storoomOper

    Private slicecount As Int64 = 0

    Private Function __hashkey(ByVal key As String, ByVal slices As vector(Of storageInterface)) As Int64
        assert(slicecount = slices.size(), "slices.size() changed after start.")
        Return signing(key) Mod slicecount
    End Function

    Private Function _key_single(ByVal key As String, ByVal slices As vector(Of storageInterface)) As storageInterface
        Return slices(__hashkey(key, slices))
    End Function

    Private Function _key_vector(ByVal key As String,
                                 ByVal slices As vector(Of storageInterface)) As vector(Of storageInterface)
        assert(Not slices Is Nothing)
        Dim rtn As vector(Of storageInterface) = Nothing
        rtn = New vector(Of storageInterface)()
        Dim slice As storageInterface = Nothing
        slice = _key_single(key, slices)
        If isdebugmode() Then
            assert(Not isCloneable(slice), "slice is cloneable, will break by vector.push_back.")
        End If
        rtn.push_back(slice)
        Return rtn
    End Function

    Private Function key_single(ByVal key As String) As storageInterface
        Return _key_single(key, slices)
    End Function

    Private Function key_vector(ByVal key As String) As vector(Of storageInterface)
        Return _key_vector(key, slices)
    End Function

    Protected MustOverride Sub setSlices()

    Public NotOverridable Overrides Sub start()
        setSlices()
        assert(slices.size() > 0)
        slicecount = slices.size()
        MyBase.start()
    End Sub

    Protected Overrides Function selectKeySlices(ByVal key As String) As vector(Of storageInterface)
        Return key_vector(key)
    End Function

    Protected Overridable Overloads Function modifyImpl(ByVal slice As storageInterface, _
                                                        ByVal key As String, _
                                                        ByVal buff As bytes) As Boolean
        Return slice.modify(key, buff)
    End Function

    Protected NotOverridable Overrides Function modifyImpl(ByVal key As String, ByVal buff As bytes, _
                                                           ByRef slice As storageInterface, _
                                                           ByVal slices As vector(Of storageInterface)) As Boolean
        assert(Not slices Is Nothing)
        assert(slices.size() = 0 OrElse slices.size() = 1)
        If slices.size() = 0 Then
            Return False
        Else
            Return threadModel().singleOper(Function(ByRef s As storageInterface) As ternary
                                                Return modifyImpl(slices(0), key, buff)
                                            End Function, slices(0)).true_()
        End If
    End Function

    'for slices_hash
    Protected Overridable Function fullImplOverride() As ternary
        Return ternary.unknown
    End Function

    Protected NotOverridable Overrides Function fullImpl(ByVal slices As vector(Of storageInterface)) As ternary
        Dim rtn As ternary = ternary.unknown
        rtn = fullImplOverride()
        If rtn = ternary.unknown Then
            Return shareTypeFull(slices)
        Else
            Return rtn
        End If
    End Function

    'for slices_hash
    Protected Overridable Function capacityImplOverride(ByRef cap As UInt64, _
                                                        ByVal slices As vector(Of storageInterface)) As ternary
        Return ternary.unknown
    End Function

    Protected NotOverridable Overrides Function capacityImpl(ByRef cap As UInt64, _
                                                             ByVal slices As vector(Of storageInterface)) As Boolean
        Dim rtn As ternary = ternary.unknown
        rtn = capacityImplOverride(cap, slices)
        If rtn = ternary.unknown Then
            If shareTypeCapacity(cap, slices) Then
                cap *= slices.size()
                Return True
            Else
                Return False
            End If
        Else
            Return ifoper(rtn = ternary.true, True, False)
        End If
    End Function
End Class
